package org.wheel.plugins.toolkit.sql.segment;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Getter;
import org.wheel.plugins.toolkit.sql.core.SqlSegment;
import org.wheel.plugins.toolkit.sql.enums.LogicalOp;
import org.wheel.plugins.toolkit.sql.plugin.RuleContext;
import org.wheel.plugins.toolkit.sql.segment.having.HavingElement;

import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * 记录阶段：整棵 SQL 逻辑树
 */
@Getter
public class SegmentTree {
    // With 语句
    private String withFromTable;
    private final List<WithSegment> withList = CollUtil.newArrayList();

    // 正常SQL逻辑树
    private String mainTable;
    private String mainAlias = "t";
    private final List<SqlSegment> selectList = CollUtil.newArrayList();
    private final List<JoinSegment> joinList = CollUtil.newArrayList();
    private final List<AbstractWhereSegment> whereSegments = CollUtil.newArrayList();
    private final List<GroupBySegment> groupBySegments = CollUtil.newArrayList();
    private HavingElement havingRoot;
    private List<OrderBySegment> orderBySegment = CollUtil.newArrayList();
    private PageSegment pageSegment;
    private final RuleContext ruleContext = new RuleContext(); // 规则上下文

    /* ========== 构造 & 链式记录 ========== */
    public SegmentTree(String mainTable) {
        this.mainTable = mainTable;
    }

    public void with(WithSegment seg) {
        withList.add(seg);
    }
    public List<WithSegment> getWithList() {
        return withList;
    }

    public void withFromTable(String withFromTable) {
        this.withFromTable = withFromTable;
    }

    public SegmentTree as(String alias) {
        this.mainAlias = alias;
        return this;
    }

    public SegmentTree select(SqlSegment... segments) {
        Collections.addAll(selectList, segments);
        return this;
    }

    public SegmentTree select(List<SqlSegment> segments) {
        selectList.addAll(segments);
        return this;
    }

    public SegmentTree join(JoinType joinType, String table, String alias, OnSegment on) {
        joinList.add(new JoinSegment(table, alias, joinType, on));
        return this;
    }

    public SegmentTree where(AbstractWhereSegment where) {
        this.whereSegments.add(where);
        return this;
    }

    public Optional<String> buildWhereSql() {
        if (whereSegments.isEmpty()) {
            return Optional.empty();
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < whereSegments.size(); i++) {
            AbstractWhereSegment p = whereSegments.get(i);
            // 第一段前面不加 AND/OR
            if (i != 0) {
                String op = p.getLogicalOp()==null?"":p.getLogicalOp().name();
                sb.append(' ').append(op).append(' ');
            }
            sb.append(p.isBeginBracket()?"(":"").append(p.getSql()).append(p.isEndBracket()?")" : "");
        }

        return Optional.of(sb.toString());
    }

    public SegmentTree groupBy(GroupBySegment groupBy) {
        this.groupBySegments.add(groupBy);
        return this;
    }

    /* ---------- having 链式入口 ---------- */
    public SegmentTree having(HavingElement root) {
        this.havingRoot = root;
        return this;
    }
    /* ---------- 帮助：获取最新 join 别名（用于 selectDeferred） ---------- */
//    public Optional<String> getLatestJoinAlias(Class<?> entityClass) {
//        return joinList.stream()
//                .filter(j -> entityClass.getSimpleName()
//                        .equalsIgnoreCase(j.getTable()))
//                .reduce((first, last) -> last)
//                .map(JoinSegment::getAlias);
//    }

    public SegmentTree page(PageSegment page) {
        this.pageSegment = page;
        return this;
    }

    public SegmentTree orderBy(OrderBySegment orderBy) {
        if(orderBy != null) {
            this.orderBySegment.add(orderBy);
        }
        return this;
    }

    public void enableRule(String ruleName) {
        ruleContext.enableRule(ruleName);
    }
}